package org.fujene.communicate.indexer.content;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import org.fujene.toolbox.ByteConverter;
import org.msgpack.MessagePackObject;
import org.msgpack.object.ArrayType;
import org.msgpack.object.IntegerType;
import org.msgpack.object.RawType;

public class ContentIndexerPackage{
	private int cluster;
	private long ID;
	private String[] contents;
	private String[] appendices;

	private ContentIndexerPackage(){
		this.cluster = -1;
		this.ID = -1L;
	}

	public ContentIndexerPackage(long ID, String[] content, String[] appendices){
		this.cluster = -1;
		this.ID = ID;
		this.contents = content;
		this.appendices = appendices;
	}

	public static ContentIndexerPackage fromRemote(ArrayType remoteContent){
		ContentIndexerPackage pkg = new ContentIndexerPackage();
		MessagePackObject[] objs = remoteContent.asArray();

		pkg.cluster = objs[0].asInt();
		pkg.ID = objs[1].asLong();
		pkg.contents = new String[objs[2].asInt()];
		pkg.appendices = new String[objs[3].asInt()];
		int index = 4;
		for(int i = 0; i < pkg.contents.length; i++)
			pkg.contents[i] = objs[index + i].asString();
		index += pkg.contents.length;
		for(int i = 0; i < pkg.appendices.length; i++)
			pkg.appendices[i] = objs[index + i].asString();

		return pkg;
	}
	
	public static ContentIndexerPackage fromByteArray(byte[] array) {
		ContentIndexerPackage pkg = new ContentIndexerPackage();
		ByteArrayInputStream stream = new ByteArrayInputStream(array);
		byte[] readb;
		int length;
		
		try{
			readb = new byte[2];
			stream.read(readb);
			pkg.cluster = ByteConverter.byteToInt(readb);
			
			readb = new byte[8];
			stream.read(readb);
			pkg.ID = ByteConverter.byteToLong(readb);
			
			readb = new byte[2];
			stream.read(readb);
			pkg.contents = new String[ByteConverter.byteToInt(readb)];
			for(int i = 0; i < pkg.contents.length; i++){
				readb = new byte[2];
				stream.read(readb);
				length = ByteConverter.byteToInt(readb);
				readb = new byte[length];
				stream.read(readb);
				pkg.contents[i] = new String(readb, Charset.forName("UTF-8"));
			}

			readb = new byte[2];
			stream.read(readb);
			pkg.appendices = new String[ByteConverter.byteToInt(readb)];
			for(int i = 0; i < pkg.appendices.length; i++){
				readb = new byte[2];
				stream.read(readb);
				length = ByteConverter.byteToInt(readb);
				readb = new byte[length];
				stream.read(readb);
				pkg.appendices[i] = new String(readb, Charset.forName("UTF-8"));
			}
		}catch(IOException ignored){
		}
		
		return pkg;
	}

	public ArrayType getRemoteContent(){
		MessagePackObject[] remoteArray = new MessagePackObject[4 + contents.length + appendices.length];

		remoteArray[0] = IntegerType.create(cluster);
		remoteArray[1] = IntegerType.create(ID);
		remoteArray[2] = IntegerType.create(contents.length);
		remoteArray[3] = IntegerType.create(appendices.length);
		int index = 4;
		for(int i = 0; i < contents.length; i++)
			remoteArray[index + i] = RawType.create(contents[i]);
		index += contents.length;
		for(int i = 0; i < appendices.length; i++)
			remoteArray[index + i] = RawType.create(appendices[i]);

		return ArrayType.create(remoteArray);
	}

	public byte[] getByteArray(){
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		byte[] contentb;

		try{
			stream.write(ByteConverter.intToByte(cluster, 2));
			stream.write(ByteConverter.longToByte(ID, 8));
			stream.write(ByteConverter.intToByte(contents.length, 2));
			stream.write(ByteConverter.intToByte(appendices.length, 2));
			for(int i = 0; i < contents.length; i++) {
				contentb = contents[i].getBytes(Charset.forName("UTF-8"));
				stream.write(ByteConverter.intToByte(contentb.length, 2));
				stream.write(contentb);
			}
			for(int i = 0; i < appendices.length; i++) {
				contentb = appendices[i].getBytes(Charset.forName("UTF-8"));
				stream.write(ByteConverter.intToByte(contentb.length, 2));
				stream.write(contentb);
			}
		}catch(IOException ignored){}
		
		return stream.toByteArray();
	}

	public void setCluster(int cluster){
		this.cluster = cluster;
	}

	public int cluster(){
		return cluster;
	}

	public long ID(){
		return ID;
	}

	public String content(int index){
		return contents[index];
	}
	
	public int contentSize() {
		return contents.length;
	}

	public String appendix(int index){
		return appendices[index];
	}
	
	public int appendixSize() {
		return appendices.length;
	}
}
